package IC.AST;

public class BinaryOperationExpression extends Expression
{
	private Operation _operation;
	private Expression _firstExp, _secondExp;
	
	public Object Visit(Visitor visitor) { return visitor.Visit(this); }
	
	public BinaryOperationExpression(Operation operation, Expression firstExp, Expression secondExp)
	{
		super(new Interval());
		_operation = operation;
		_firstExp = firstExp;
		_secondExp = secondExp;
		GiveBirth(_firstExp);
		GiveBirth(_secondExp);
	}
	
	public Operation GetOperation() { return _operation; }
	public Expression GetFirstExp() { return _firstExp; }
	public Expression GetSecondExp() { return _secondExp; } 
	
	public enum OperationType {Integer, Boolean, NotSet};
	
	public enum Operation
	{
		Add ("+", OperationType.NotSet, 0),
		Sub ("-", OperationType.Integer, 1),
		Mult ("*", OperationType.Integer, 2),
		Div ("/", OperationType.Integer, 3),
		Mod ("%", OperationType.Integer, 4),
		And ("&&", OperationType.Boolean, 5),
		Or ("||", OperationType.Boolean, 6),
		Less ("<", OperationType.Boolean, 7),
		LessOrEqual ("<=", OperationType.Boolean, 8),
		More (">", OperationType.Boolean, 9),
		MoreOrEqual (">=", OperationType.Boolean, 10),
		Equal ("==", OperationType.Boolean, 11),
		NotEqual ("!=", OperationType.Boolean, 12);
		
		private String _string;
		private OperationType _type;
		private int _id;
		
		private Operation (String string, OperationType type, int id)
		{
			_string = string;
			_type = type;
			_id = id;
		}
		
		public boolean equals(Operation op) { return _id == op._id; }
		public String toString() { return new String(_string); }
		public OperationType GetType() { return _type; }
		
		public boolean EvaluateBooleanExpression(int first, int second)
		{
			switch (this)
			{
			case And:
				return IntToBool(first) && IntToBool(second);
			case Or:
				return IntToBool(first) || IntToBool(second);
			case Equal:
				return first == second;
			case NotEqual:
				return first != second;
			case Less:
				return first < second;
			case LessOrEqual:
				return first <= second;
			case More:
				return first > second;
			case MoreOrEqual:
				return first >= second;
			default:
				return false;
			}
		}
		
		
		public int EvaluateIntegerExpression(int first, int second)
		{
			switch (this)
			{
			case Add:
				return first + second;
			case Sub:
				return first - second;
			case Div:
				return first / second;
			case Mult:
				return first * second;
			case Mod:
				return first % second;
			default:
				return 0;
			}
		}
		
		public boolean Isflippable()
		{
			return this == Add || this == Mult || this == Equal || this == NotEqual;
		}
		
		private boolean IntToBool(int value) { return !(value == 0); }
	}
}
